      subroutine loop__1_host(cur_dev, loop_ref, r0000m, a, b)
      integer*8 :: cur_dev
      integer*8 :: loop_ref
      real :: r0000m(0:1)
      integer*8 :: a(7), b(7)
      integer*8 :: boundsLow(2), boundsHigh(2), stepsIgnore(2)
      integer :: j, i
      integer*8 :: a0004, a0002, b0004, b0002
      external loop_fill_bounds
      a0002 = a(2)
      a0004 = a(4)
      b0002 = b(2)
      b0004 = b(4)
      call loop_fill_bounds(loop_ref, boundsLow(1), boundsHigh(1), stepsIgnore(1))
      do j = boundsLow(1), boundsHigh(1)
         do i = boundsLow(2), boundsHigh(2)
            r0000m(a0004 + i + a0002 * j) = 0.
            if (i .eq. 1 .or. j .eq. 1 .or. i .eq. 5002 .or. j .eq. 5002) then
               r0000m(b0004 + i + b0002 * j) = 0.
            else
               r0000m(b0004 + i + b0002 * j) = 1. + i + j
            endif
         enddo
      enddo
      end subroutine loop__1_host

      subroutine loop__2_host(cur_dev, loop_ref, r0000m, a, b)
      integer*8 :: cur_dev
      integer*8 :: loop_ref
      real :: r0000m(0:1)
      integer*8 :: a(7), b(7)
      integer*8 :: boundsLow(2), boundsHigh(2), stepsIgnore(2)
      integer :: j, i
      integer*8 :: a0004, a0002, b0004, b0002
      real :: eps
      integer :: ijmax(2)
      real :: tmp
      integer*8  dvm0c0
      parameter (dvm0c0 = 0)
      external loop_fill_bounds, loop_red_init, loop_red_post
      a0002 = a(2)
      a0004 = a(4)
      b0002 = b(2)
      b0004 = b(4)
      call loop_fill_bounds(loop_ref, boundsLow(1), boundsHigh(1), stepsIgnore(1))
      call loop_red_init(loop_ref, dvm0c0, eps, ijmax(1))
      do j = boundsLow(1), boundsHigh(1)
         do i = boundsLow(2), boundsHigh(2)
            tmp = abs (r0000m(b0004 + i + b0002 * j) - r0000m(a0004 + i + a0002 * j))
            if (tmp .gt. eps) then
               eps = tmp
               ijmax(1) = i
               ijmax(2) = j
            endif  
            r0000m(a0004 + i + a0002 * j) = r0000m(b0004 + i + b0002 * j)
         enddo
      enddo
      call loop_red_post(loop_ref, dvm0c0, eps, ijmax(1))
      end subroutine loop__2_host

      subroutine loop__3_host(cur_dev, loop_ref, r0000m, a, b)
      integer*8 :: cur_dev
      integer*8 :: loop_ref
      real :: r0000m(0:1)
      integer*8 :: a(7), b(7)
      integer*8 :: boundsLow(2), boundsHigh(2), stepsIgnore(2)
      integer :: j, i
      integer*8 :: a0004, a0002, b0004, b0002
      external loop_fill_bounds
      a0002 = a(2)
      a0004 = a(4)
      b0002 = b(2)
      b0004 = b(4)
      call loop_fill_bounds(loop_ref, boundsLow(1), boundsHigh(1), stepsIgnore(1))
      do j = boundsLow(1), boundsHigh(1)
         do i = boundsLow(2), boundsHigh(2)
            r0000m(b0004 + i + b0002 * j) = (r0000m(a0004 + (i - 1) + a0002 * j) + r0000m(a0004 + i + a0002 * (j - 1)) + r0000m(a0004 + (i + 1) + a0002 * j) + r0000m(a0004 + i + a0002 * (j + 1))) / 4
         enddo
      enddo
      end subroutine loop__3_host

      program jac
      parameter (l = 5002,itmax = 5000)
      real  eps,maxeps
      real  tmp
      integer  ijmax(2)
      real  startt,endt
      integer  clock_rate,clock_start,clock_end
      external ftcntr,eiof,biof,clfdvm
      integer*8  dvmlf,lindtp,delobj,arrcpy,tstio,getach,getad,getaf,getal,getai,dopl,endpl,mappl,crtpl, waitsh,strtsh,inssh,crtshg,waitrd,strtrd,insred,crtrg,crtrdf,align,crtda,distr,crtamv,lexit,linit
      integer*8  dvm000(45+4)
      integer*8  a(38),b(38)
      character*19  filenm001
      integer*8  a0004,a0002,b0004,b0002
      common /jacdvm/eps
      integer*8  dvm0c9,dvm0c8,dvm0c7,dvm0c6,dvm0c5,dvm0c4,dvm0c3,dvm0c2,dvm0c1,dvm0c0
      parameter (dvm0c9 = 9,dvm0c8 = 8,dvm0c7 = 7,dvm0c6 = 6,dvm0c5 = 5,dvm0c4 = 4,dvm0c3 = 3,dvm0c2 = 2,dvm0c1 = 1,dvm0c0 = 0)
      integer  i000io(262144)
      real  r000io(262144)
      equivalence (r000io,i000io)
      character  ch000m(0:64)
      logical  l0000m(0:64)
      double precision  d0000m(0:64)
      real  r0000m(0:64)
      integer  i0000m(0:64)
      equivalence (l0000m,d0000m,r0000m,i0000m)
      common /mem000/i0000m
      integer  idvm01
      integer  idvm00

! DVMH declarations
      external init_cuda, loop__1_cuda, loop__2_cuda, loop__3_cuda
      external loop__1_host, loop__2_host, loop__3_host
      external dvmh_init, dvmh_shadow_renew, dvmh_get_actual_scalar, dvmh_get_actual_subarray, dvmh_actual_scalar
      external region_register_subarray, region_register_scalar, region_prepared_for_devices, region_inner_start, region_end
      external loop_insred, loop_set_cuda_block, loop_register_handler, loop_start, loop_end
      integer*8 dvmh_get_actual_edges, region_create, loop_create

      integer*8 DEVICE_TYPE_HOST, DEVICE_TYPE_CUDA
      parameter (DEVICE_TYPE_HOST = 1, DEVICE_TYPE_CUDA = 2)
      integer*8 HANDLER_TYPE_PARALLEL, HANDLER_TYPE_MASTER
      parameter (HANDLER_TYPE_PARALLEL = 1, HANDLER_TYPE_MASTER = 2)
      integer INTENT_IN, INTENT_OUT, INTENT_LOCAL
      parameter (INTENT_IN = 1, INTENT_OUT = 2, INTENT_LOCAL = 4)

      data filenm001/'jac_gpu_maxloc.fdv '/ 
      filenm001(19:19) = char (0)
      dvm000(1) = 13
      dvm000(1) = dvmlf (dvm000(1),filenm001)
      dvm000(1) = dvm0c6
      dvm000(2) = getai (dvm000(1))
      dvm000(3) = getai (i0000m(0))
      dvm000(4) = getal (l0000m(0))
      dvm000(5) = getaf (r0000m(0))
      dvm000(6) = getad (d0000m(0))
      dvm000(7) = getach (ch000m(0))
      dvm000(8) = getai (dvm000(2))
      dvm000(9) = getai (i0000m(1))
      dvm000(10) = getal (l0000m(1))
      dvm000(11) = getaf (r0000m(1))
      dvm000(12) = getad (d0000m(1))
      dvm000(13) = getach (ch000m(1))
      i0000m(0) = 8
      i0000m(1) = 4
      i0000m(2) = 4
      i0000m(3) = 4
      i0000m(4) = 8
      i0000m(5) = 1
      i0000m(10) = 2
      i0000m(11) = 1
      i0000m(12) = 1
      i0000m(13) = 3
      i0000m(14) = 4
      i0000m(15) = 5
      call ftcntr(6,dvm000(2),dvm000(8),i0000m(0),i0000m(10))
      dvm000(1) = linit (dvm0c0)
      dvm000(4) = 2
      dvm000(5) = 1
      dvm000(6) = 0
      dvm000(7) = 0
      dvm000(8) = 9
      dvm000(8) = dvmlf (dvm000(8),filenm001)
      dvm000(8) = 5002
      dvm000(9) = 5002
      dvm000(10) = crtamv (dvm0c0,dvm0c2,dvm000(8),dvm0c0)
      dvm000(11) = distr (dvm000(10),dvm0c0,dvm0c2,dvm000(4),dvm000(6))

! Some initializations
      call dvmh_init()
      call init_cuda()

      dvm000(12) = 1
      dvm000(13) = 1
      a(5) = 1
      a(6) = 1
      a(7) = 8
      dvm000(14) = crtda (a(1),dvm0c1,i0000m,dvm0c2, (-(dvm0c3)),dvm000(8),dvm0c0,dvm0c0,dvm000(12),dvm000(12))
      dvm000(15) = 1
      dvm000(16) = 2
      dvm000(17) = 1
      dvm000(18) = 1
      dvm000(19) = 0
      dvm000(20) = 0
      dvm000(21) = align (a(1),dvm000(10),dvm000(15),dvm000(17),dvm000(19))
      dvm000(12) = 1
      dvm000(13) = 2
      dvm000(14) = 1
      dvm000(15) = 1
      dvm000(16) = 0
      dvm000(17) = 0
      dvm000(18) = 10
      dvm000(18) = dvmlf (dvm000(18),filenm001)
      dvm000(18) = 5002
      dvm000(19) = 5002
      dvm000(20) = 1
      dvm000(21) = 1
      b(5) = 1
      b(6) = 1
      b(7) = 8
      dvm000(22) = crtda (b(1),dvm0c1,i0000m,dvm0c2, (-(dvm0c3)),dvm000(18),dvm0c0,dvm0c0,dvm000(20),dvm000(20))
      dvm000(23) = align (b(1),a(1),dvm000(12),dvm000(14),dvm000(16))
      dvm000(11) = 13
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      call biof()

!		 arrays A and B  with block distribution 
      if (tstio () .ne. 0)       print *, '**********  TEST_JACOBI   **********'
      call eiof()
      maxeps = 0.5e-7

! Start synchronous region
      dvm000(45) = region_create(dvm0c0)
! Whole arrays A and B. out(A, B)
      dvm000(46) = -2147483648
      dvm000(47) = -2147483648
      call region_register_subarray(dvm000(45), INTENT_OUT, a, dvm000(46), dvm000(46))
      call region_register_subarray(dvm000(45), INTENT_OUT, b, dvm000(46), dvm000(46))
! Pass bitmask of device types that can be used due to compiler options and region inner limitations
      call region_prepared_for_devices(dvm000(45), ior(DEVICE_TYPE_HOST, DEVICE_TYPE_CUDA))
! Signals start of execution
      call region_inner_start(dvm000(45))

      dvm000(11) = 16
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      b0002 = b(2)
      b0004 = b(4)
      a0002 = a(2)
      a0004 = a(4)
      dvm000(11) = crtpl (dvm0c2)
      dvm000(18) = getai (j)
      dvm000(19) = getai (i)
      dvm000(20) = 1
      dvm000(21) = 1
      dvm000(22) = 1
      dvm000(23) = 1
      dvm000(24) = l
      dvm000(25) = l
      dvm000(26) = 1
      dvm000(27) = 1
      dvm000(28) = 1
      dvm000(29) = 2
      dvm000(30) = 1
      dvm000(31) = 1
      dvm000(32) = (-1)
      dvm000(33) = (-1)
      dvm000(34) = mappl (dvm000(11),a(1),dvm000(28),dvm000(30),dvm000(32),dvm000(18),dvm000(20),dvm000(22),dvm000(24),dvm000(26),dvm000(12),dvm000(14),dvm000(16))
90000 continue
      dvm000(35) = 19
      dvm000(35) = dvmlf (dvm000(35),filenm001)
      dvm000(35) = dopl (dvm000(11))
      if (dvm000(35) .eq. 0)       goto 89999


! Parallel loop
      dvm000(46) = loop_create(dvm000(45), dvm000(11))
! Registering handlers for parallel loop
      call loop_register_handler(dvm000(46), DEVICE_TYPE_HOST, dvm0c0, loop__1_host, dvm0c0, dvm0c3, r0000m, a, b)
      call loop_register_handler(dvm000(46), DEVICE_TYPE_CUDA, dvm0c0, loop__1_cuda, dvm0c0, dvm0c2, a, b)
! Start execution
      call loop_start(dvm000(46))
! Loop end
      call loop_end(dvm000(46))

      goto 90000
89999 continue
      dvm000(36) = 27
      dvm000(36) = dvmlf (dvm000(36),filenm001)
      dvm000(36) = endpl (dvm000(11))

! Compute region ending
      call region_end(dvm000(45))

      call cpu_time(startt)
      call system_clock(count_rate=clock_rate)
      call system_clock(count=clock_start)
      do 2 it = 1,itmax
         eps = 0.

! Declare eps as actual
         call dvmh_actual_scalar(eps)

! Register compute region and distributed arrays
         dvm000(45) = region_create(dvm0c0)
! Whole arrays A and B. inout(A, B)
         dvm000(46) = -2147483648
         dvm000(47) = -2147483648
         call region_register_subarray(dvm000(45), ior(INTENT_IN, INTENT_OUT), a, dvm000(46), dvm000(46))
         call region_register_subarray(dvm000(45), ior(INTENT_IN, INTENT_OUT), b, dvm000(46), dvm000(46))
! Scalar variable EPS. inout(EPS)
         call region_register_scalar(dvm000(45), ior(INTENT_IN, INTENT_OUT), eps, dvm0c4)
! Scalar variable IJMAX. out(IJMAX). Actually, this is an array, but it is not distributed and we don't want to cut sections from it, so it has no difference from scalar.
         call region_register_scalar(dvm000(45), INTENT_OUT, ijmax, dvm0c8)
! Pass bitmask of device types that can be used due to compiler options and region inner limitations
         call region_prepared_for_devices(dvm000(45), ior(DEVICE_TYPE_HOST, DEVICE_TYPE_CUDA))
! Signals start of execution
         call region_inner_start(dvm000(45))

         dvm000(11) = 36
         dvm000(11) = dvmlf (dvm000(11),filenm001)
         a0002 = a(2)
         a0004 = a(4)
         b0002 = b(2)
         b0004 = b(4)
         dvm000(18) = crtrg (dvm0c1,dvm0c1)
         dvm000(36) = 1
         dvm000(37) = 2 * 4
         dvm000(38) = crtrdf (dvm0c3,getaf (eps),dvm0c3,dvm000(36),ijmax,dvm000(37),dvm0c1)
         dvm000(39) = lindtp (dvm000(38),dvm0c1)
         dvm000(11) = crtpl (dvm0c2)
         dvm000(19) = getai (j)
         dvm000(20) = getai (i)
         dvm000(21) = 1
         dvm000(22) = 1
         dvm000(23) = 2
         dvm000(24) = 2
         dvm000(25) = l - 1
         dvm000(26) = l - 1
         dvm000(27) = 1
         dvm000(28) = 1
         dvm000(29) = 1
         dvm000(30) = 2
         dvm000(31) = 1
         dvm000(32) = 1
         dvm000(33) = (-1)
         dvm000(34) = (-1)
         dvm000(35) = mappl (dvm000(11),a(1),dvm000(29),dvm000(31),dvm000(33),dvm000(19),dvm000(21),dvm000(23),dvm000(25),dvm000(27),dvm000(12),dvm000(14),dvm000(16))
         dvm000(40) = insred (dvm000(18),dvm000(38),dvm000(11),dvm0c0)
89997    continue
         dvm000(41) = 39
         dvm000(41) = dvmlf (dvm000(41),filenm001)
         dvm000(41) = dopl (dvm000(11))
         if (dvm000(41) .eq. 0)          goto 89996

! Parallel loop
         dvm000(46) = loop_create(dvm000(45), dvm000(11))
         call loop_insred(dvm000(46), dvm000(38))
! Registering handlers for parallel loop
         call loop_register_handler(dvm000(46), DEVICE_TYPE_HOST, dvm0c0, loop__2_host, dvm0c0, dvm0c3, r0000m, a, b)
         call loop_register_handler(dvm000(46), DEVICE_TYPE_CUDA, dvm0c0, loop__2_cuda, dvm0c0, dvm0c2, a, b)
! Setting additional options
         dvm000(47) = 256
         call loop_set_cuda_block(dvm000(46), dvm000(47), dvm0c1, dvm0c1)
! Start execution
         call loop_start(dvm000(46))
! Loop end
         call loop_end(dvm000(46))

         goto 89997
89996    continue
         dvm000(42) = 49
         dvm000(42) = dvmlf (dvm000(42),filenm001)
         dvm000(42) = endpl (dvm000(11))
         dvm000(43) = getaf (eps)
         dvm000(43) = getai (ijmax(1))
         dvm000(43) = strtrd (dvm000(18))
         dvm000(44) = waitrd (dvm000(18))
         dvm000(44) = delobj (dvm000(18))
         dvm000(11) = 50
         dvm000(11) = dvmlf (dvm000(11),filenm001)
         a0002 = a(2)
         a0004 = a(4)
         b0002 = b(2)
         b0004 = b(4)
         dvm000(11) = crtpl (dvm0c2)
         dvm000(18) = crtshg (dvm0c0)
         dvm000(19) = (-1)
         dvm000(20) = (-1)
         dvm000(21) = inssh (dvm000(18),a(1),dvm000(19),dvm000(19),dvm0c0)

! Update host edge elements
         dvm000(47) = dvmh_get_actual_edges(dvm000(18))

         dvm000(22) = strtsh (dvm000(18))
         dvm000(23) = getai (j)
         dvm000(24) = getai (i)
         dvm000(25) = 1
         dvm000(26) = 1
         dvm000(27) = 2
         dvm000(28) = 2
         dvm000(29) = l - 1
         dvm000(30) = l - 1
         dvm000(31) = 1
         dvm000(32) = 1
         dvm000(33) = 1
         dvm000(34) = 2
         dvm000(35) = 1
         dvm000(36) = 1
         dvm000(37) = (-1)
         dvm000(38) = (-1)
         dvm000(39) = waitsh (dvm000(18))

! Update shadow elements on devices involved into region execution
         call dvmh_shadow_renew(dvm000(45), dvm000(47))

         dvm000(40) = mappl (dvm000(11),b(1),dvm000(33),dvm000(35),dvm000(37),dvm000(23),dvm000(25),dvm000(27),dvm000(29),dvm000(31),dvm000(12),dvm000(14),dvm000(16))
89994    continue
         dvm000(41) = 53
         dvm000(41) = dvmlf (dvm000(41),filenm001)
         dvm000(41) = dopl (dvm000(11))
         if (dvm000(41) .eq. 0)          goto 89993

! Parallel loop
         dvm000(46) = loop_create(dvm000(45), dvm000(11))
! Registering handlers for parallel loop
         call loop_register_handler(dvm000(46), DEVICE_TYPE_HOST, dvm0c0, loop__3_host, dvm0c0, dvm0c3, r0000m, a, b)
         call loop_register_handler(dvm000(46), DEVICE_TYPE_CUDA, dvm0c0, loop__3_cuda, dvm0c0, dvm0c2, a, b)
! Setting additional options
         dvm000(47) = 256
         call loop_set_cuda_block(dvm000(46), dvm000(47), dvm0c1, dvm0c1)
! Start execution
         call loop_start(dvm000(46))
! Loop end
         call loop_end(dvm000(46))

         goto 89994
89993    continue
         dvm000(42) = 57
         dvm000(42) = dvmlf (dvm000(42),filenm001)
         dvm000(42) = endpl (dvm000(11))
         dvm000(11) = 60
         dvm000(11) = dvmlf (dvm000(11),filenm001)
         call biof()

! Compute region ending
         call region_end(dvm000(45))

! get_actual(EPS, IJMAX)
         call dvmh_get_actual_scalar(eps)
         call dvmh_get_actual_scalar(ijmax(1))

         if (tstio () .ne. 0)          print 200, it,eps,ijmax(1),ijmax(2)
         call eiof()
200                  FORMAT(' IT = ', I4, '   EPS = ', E14.7, '   Imax = ', I4, '   Jmax = ', I4)
         if (eps .lt. maxeps)          goto 3
2        continue
3     continue


! get_actual(B)
      dvm000(45) = -2147483648
      dvm000(46) = -2147483648
      call dvmh_get_actual_subarray(b, dvm000(45), dvm000(45))

      call cpu_time(endt)
      call system_clock(count=clock_end)
      dvm000(11) = 69
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      call biof()
      if (tstio () .ne. 0)       print *, 'time = ',endt - startt,'clock = ',real (clock_end - clock_start) / clock_rate
      call eiof()
      dvm000(11) = 71
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      call biof()
      if (tstio () .ne. 0)       open (unit = 3,file = 'JAC.DAT',form = 'FORMATTED',status = 'UNKNOWN')
      call eiof()
      dvm000(11) = 72
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      call biof()
      do 89991 idvm01 = 0,5001,52
         if (idvm01 + 52 .le. 5002) then
            dvm000(11) = 52
         else  
            dvm000(11) = 5002 - idvm01
         endif  
         dvm000(12) = idvm01
         dvm000(13) = (-1)
         dvm000(14) = idvm01 + dvm000(11) - 1
         dvm000(16) = 1
         dvm000(18) = arrcpy (b(1),dvm000(12),dvm000(14),dvm000(16),i000io(1),dvm000(12),dvm000(14),dvm000(16),dvm0c2)
         if (tstio () .ne. 0)          write (unit = 3,fmt = *) (r000io(idvm00), idvm00 = 1,dvm000(11) * 5002)
89991    continue
      call eiof()
      dvm000(11) = 73
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      call biof()
      if (tstio () .ne. 0)       close (unit = 3)
      call eiof()
      dvm000(11) = 74
      dvm000(11) = dvmlf (dvm000(11),filenm001)
      call clfdvm()
      dvm000(11) = lexit (dvm0c0)
      end

